<?php
declare(strict_types=1);

namespace LowCode\Naive;

use Closure;
use LowCode\Html;
use LowCode\Naive;
use LowCode\Node;
use LowCode\Support\JsExp;

/**
 * Carousel 轮播图组件
 * @method static static make(array $images = []) Carousel轮播图组件
 * to (index: number) => void	滑动至某一页	2.24.0
 * prev	() => void	滑动至前一页	2.24.0
 * next	() => void	滑动至后一页	2.24.0
 * getCurrentIndex	() => number	获取当前页
 */
class Carousel extends Naive
{
    protected array $images = [];

    protected ?Closure $closure = null;

    /**
     * @param array $images
     */
    public function __construct(array $images = [])
    {
        parent::__construct();
        $this->images = $images;
    }

    /**
     * @param Closure|null $closure
     * @return $this
     */
    public function withClosure(Closure $closure = null): static
    {
        $this->closure = $closure;
        return $this;
    }

    /**
     * 是否自动播放
     * @param bool|JsExp $bool
     * @return $this
     */
    public function autoplay(bool|JsExp $bool = true): static
    {
        return $this->prop('autoplay', $bool);
    }

    /**
     * 是否居中显示当前页轮播图
     * @param bool|JsExp $bool
     * @return $this
     */
    public function centeredSlides(bool|JsExp $bool = true): static
    {
        return $this->prop('centered-slides', $bool);
    }

    /**
     * 当前显示页
     * @param int|JsExp $index
     * @return $this
     */
    public function currentIndex(int|JsExp $index = 0): static
    {
        return $this->prop('current-index', $index);
    }

    /**
     * 默认显示页
     * @param int|JsExp $index
     * @return $this
     */
    public function defaultIndex(int|JsExp $index = 0): static
    {
        return $this->prop('default-index', $index);
    }

    /**
     *    轮播图显示的方向
     * @param string|JsExp $direction
     * @return $this
     */
    public function direction(string|JsExp $direction = 'horizontal' | 'vertical'): static
    {
        return $this->prop('direction', $direction);
    }


    /**
     *    轮播指示点位置
     * @param string|JsExp $placement
     * @return $this
     */
    public function dotPlacement(string|JsExp $placement ='top' | 'bottom' | 'left' | 'right'): static
    {
        return $this->prop('dot-placement', $placement);
    }

    /**
     *    轮播指示点位置
     * @param string|JsExp $dotType
     * @return $this
     */
    public function dotType(string|JsExp $dotType ='dot' | 'line'): static
    {
        return $this->prop('dot-type', $dotType);
    }

    /**
     * 轮播指示点位置
     * @param string|JsExp $effect
     * @return $this
     */
    public function effect(string|JsExp $effect ='slide' | 'fade' | 'card' | 'custom'): static
    {
        return $this->prop('effect', $effect);
    }

    /**
     * 自动播放的间隔（ms）
     * @param int|JsExp $interval
     * @return $this
     */
    public function interval(int|JsExp $interval = 5000): static
    {
        return $this->prop('interval', $interval);
    }

    /**
     * 是否通过按键切换轮播图，只有焦点在 Dots 上时才起作用
     * @param bool|JsExp $bool
     * @return $this
     */
    public function keyboard(bool|JsExp $bool = true): static
    {
        return $this->prop('keyboard', $bool);
    }

    /**
     * 是否循环播放
     * @param bool|JsExp $bool
     * @return $this
     */
    public function loop(bool|JsExp $bool = true): static
    {
        return $this->prop('loop', $bool);
    }

    /**
     * 是否通过鼠标滚轮切换轮播图
     * @param bool|JsExp $bool
     * @return $this
     */
    public function mousewheel(bool|JsExp $bool = true): static
    {
        return $this->prop('mousewheel', $bool);
    }

    /**
     * 下一张轮播图的样式
     * @param array|string|JsExp $style
     * @return $this
     */
    public function nextSlideStyle(array|string|JsExp $style = []): static
    {
        return $this->prop('next-slide-style', $style);
    }

    /**
     * 上一张轮播图的样式
     * @param array|string|JsExp $style
     * @return $this
     */
    public function prevSlideStyle(array|string|JsExp $style = []): static
    {
        return $this->prop('prev-slide-style', $style);
    }

    /**
     * 每一页显示的轮播图数量
     * @param int|string|JsExp $number 'auto' | number
     * @return $this
     */
    public function slidesPerView(int|string|JsExp $number = 1): static
    {
        return $this->prop('slides-per-view', $number);
    }

    /**
     * 轮播图之间的间距
     * @param int|JsExp $number 0
     * @return $this
     */
    public function spaceBetween(int|JsExp $number = 0): static
    {
        return $this->prop('space-between', $number);
    }

    /**
     * 是否显示箭头按钮
     * @param bool|JsExp $bool
     * @return $this
     */
    public function showArrow(bool|JsExp $bool = true): static
    {
        return $this->prop('show-arrow', $bool);
    }

    /**
     * 是否展示指示点
     * @param bool|JsExp $bool
     * @return $this
     */
    public function showDots(bool|JsExp $bool = true): static
    {
        return $this->prop('show-dots', $bool);
    }


    /**
     * 是否通过触摸拖拽切换轮播图
     * @param bool|JsExp $bool
     * @return $this
     */
    public function touchable(bool|JsExp $bool = true): static
    {
        return $this->prop('touchable', $bool);
    }

    /**
     * 过渡效果的样式
     * @param array|JsExp $style { transitionDuration?: string, transitionTimingFunction?: string }
     * @return $this
     */
    public function transitionStyle(array|JsExp $style = []): static
    {
        return $this->prop('transition-style', $style);
    }

    /**
     * 自定义过渡效果属性，参考 Vue 文档
     * @param array|string|JsExp $props TransitionProps
     * @return $this
     */
    public function transitionProps(array|string|JsExp $props = []): static
    {
        return $this->prop('transition-props', $props);
    }

    /**
     * 触发切换的方式
     * @param string|JsExp $trigger
     * @return $this
     */
    public function trigger(string|JsExp $trigger = 'click' | 'hover'): static
    {
        return $this->prop('trigger', $trigger);
    }

    /**
     * 当前页变化时的回调函数
     * @param string $event (currentIndex: number, lastIndex: number) => void
     * @param string|null $id
     * @param array $modifiers
     * @return $this
     */
    public function onUpdateCurrentIndex(string $event, string $id = null, array $modifiers = []): static
    {
        return $this->event('update:current-index', jsFn($event, $id), $modifiers);
    }

    /**
     * 设置 slot arrow 内容 $params = ["total","currentIndex","to","prev","next"]
     * @param Node $node
     * @param array $params (info: { total: number, currentIndex: number, to: (index: number) => void, prev: () => void, next: () => void })
     * @return $this
     */
    public function slotArrow(Node $node, array $params = ["total","currentIndex","to","prev","next"]): static
    {
        return $this->addSlot($node, "arrow",$params);
    }

    /**
     * 设置 slot dots 内容 $params = ["total","currentIndex","to"]
     * @param Node $node
     * @param array $params (info: { total: number, currentIndex: number, to: (index: number) => void })
     * @return $this
     */
    public function slotDots(Node $node, array $params = ["total","currentIndex","to"]): static
    {
        return $this->addSlot($node, "dots",$params);
    }


    public function jsonSerialize():array
    {
        if ($this->images){
            $children = array_map(function ($image){
                if ($image instanceof Node){
                    $img = $image;
                }else{
                    $img = Html::img();
                    $img->prop("src",$image);
                }
                if ($this->closure instanceof Closure){
                    call_user_func($this->closure,$img);
                }
                return $img;
            },$this->images);
            $this->children($children);
        }
        return parent::jsonSerialize();
    }

}
